筆記目錄

Skip to content

升級至 .NET 6 時多餘 AsQueryable() 呼叫的原因

我一樣是直接寫 .NET 6 的人,看到從 .NET Core 3.1 升上來的專案,可能會看到這樣的程式碼 DbContext.Table.AsQueryable(),可能會疑惑 DbSet<TEntity> 本來就有實作 IQueryable<TEntity>,為何還需要呼叫 AsQueryable(),實際上移除掉看起來也可以正常。如果遇到這情況,可以看一下此專案是否有安裝 System.Linq.Async 這個套件。

在 Microsoft.EntityFrameworkCore 5 以前的版本,DbSet<TEntity> 實作的介面如下:

csharp
public abstract class DbSet<TEntity> : Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>, System.Collections.Generic.IAsyncEnumerable<TEntity>, System.Collections.Generic.IEnumerable<TEntity>, System.ComponentModel.IListSource, System.Linq.IQueryable<TEntity> where TEntity : class

Queryable 類別裡定義了 IQueryable<TEntity> 的擴充方法 Where()Select()

而在 System.Linq.Async 的 AsyncEnumerable 類別裡定義了 IAsyncEnumerable<TSource> 的擴充方法 Where()Select(),這導致了 DbSet<TEntity> 無法辨識應該呼叫哪個擴充方法,必須使用 AsQueryable() 將宣告型別改為 IQueryable<TEntity>,也因此從舊版升上來的專案,容易會殘留很多多餘的 AsQueryable()

在 Microsoft.EntityFrameworkCore 6 以後的版本,DbSet<TEntity> 實作的介面如下:

csharp
public abstract class DbSet<TEntity> : Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>, System.Collections.Generic.IEnumerable<TEntity>, System.ComponentModel.IListSource, System.Linq.IQueryable<TEntity> where TEntity : class

因此,即便安裝了 System.Linq.Async,也不會出現呼叫模糊的問題。

異動歷程

  • 2024-07-16 初版文件建立。